﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

#endregion

namespace MetaHeuristics.Tsp
{
    /// <summary>
    /// A Travelling Salesman Problem (TSP) class.
    /// </summary>
    public class TspProblem
    {
        private float optimalLength = 3000;
        private int maxIteration = 1000;
        private TimeSpan maxDuration = new TimeSpan(1, 0, 0);
        private CityCollection cities = new CityCollection();
        private RectangleF cityBounds=new RectangleF();

        /// <summary>
        /// Initializes an empty instance of a TSP
        /// </summary>
        public TspProblem()
        { }

        /// <summary>
        /// Gets or sets the lower bound on the optimal length
        /// </summary>
        /// <value></value>
        public float OptimalLength
        {
            get
            {
                return this.optimalLength;
            }
            set
            {
                this.optimalLength = value;
            }
        }

        /// <summary>
        /// Gets or sets the maximum number of algorithm iteration.
        /// </summary>
        /// <value>
        /// A value indicating the maximum number of iteration.
        /// </value>
        public int MaxIteration
        {
            get
            {
                return this.maxIteration;
            }
            set
            {
                this.maxIteration = value;
            }
        }

        /// <summary>
        /// Gets or sets the maximum duration of algorithm execution.
        /// </summary>
        /// <value>
        /// A value indicating the maximum duration of execution.
        /// </value>
        public TimeSpan MaxDuration
        {
            get
            {
                return this.maxDuration;
            }
            set
            {
                this.maxDuration = value;
            }
        }

        /// <summary>
        /// Gets a collection of cities used to define the TSP problem.
        /// </summary>
        /// <value>
        /// A <see cref="CityCollection"/> containing the cities in the TSP problem.
        /// </value>
        public CityCollection Cities
        {
            get
            {
                return this.cities;
            }
        }

        public RectangleF CityBounds
        {
            get
            {
                if (this.cityBounds.IsEmpty)
                    this.UpdateCityBounds();
                return this.cityBounds;
            }
        }

        public void UpdateCityBounds()
        {
            float left=float.MaxValue;
            float right=float.MinValue;
            float top=float.MinValue;
            float bottom=float.MaxValue;
            foreach (City city in this.Cities)
            {
                if (city.Position.X < left)
                    left = city.Position.X;
                if (city.Position.X > right)
                    right = city.Position.X;
                if (city.Position.Y < bottom)
                    bottom = city.Position.Y;
                if (city.Position.Y > top)
                    top = city.Position.Y;
            }
            this.cityBounds=new RectangleF(left, top, right - left, top - bottom);
        }

        public void AddCity(float x, float y)
        {
            City city = new City(
                (this.cities.Count+1).ToString(),
                new PointF(x,y)
                );
            this.cities.Add(city);
        }

        public override string ToString()
        {
            return String.Format("TSP, {0} cities", this.Cities.Count);
        }
    }
}
